//
// DO NOT MODIFY THIS FILE - it is generated using templatec on Generator.t
//
package lpg.tool.optionpg;

import java.io.PrintWriter;
import java.io.File; /* Generator.t:1 */
import java.util.Map; /* Generator.t:2 */
import lpg.util.Utility; /* Generator.t:3 */

class Generator
{
    private PrintWriter out = null;

    public void setOut(PrintWriter pw)
    {
        out = pw;
    }

    public void run()
    {
        out.write("\n"); /* Generator.t:1~2 */
        out.write("\n"); /* Generator.t:2~3 */
        out.write("\n//--"); /* Generator.t:3~4 */
        out.print(parserFile.getAbsolutePath()); /* Generator.t:4 */
        out.write("\n//\n// DO NOT MODIFY THIS FILE - it is generated using optionpg on lpg.OptionEnum\n//\npackage lpg;\n\nclass OptionParser\n{\n    OptionParser(Option option, char[] param, int end)\n    {\n        this.option = option;\n        this.param = param;\n        this.end = end;\n    }\n\n    int classifyOption(int start, boolean flag)\n    {\n        int p = start;\n        char c = param[start];"); /* Generator.t:4~22 */
        processOptionPath(optionMap); /* Generator.t:23 */
        out.write("\n    }\n"); /* Generator.t:24~26 */

        for (Node node : optionMap.values()) /* Generator.t:28 */
        { /* Generator.t:29 */
            processNode(node); /* Generator.t:30 */
        } /* Generator.t:31 */

        out.write("\n    private final Option option;\n    private final char[] param;\n    private final int end;\n\n}\n"); /* Generator.t:33~39 */
    }

    private final Map<Character, Node> optionMap; /* Generator.t:40 */
    private final File parserFile; /* Generator.t:41 */

    Generator(Map<Character, Node> optionMap, File parserFile, PrintWriter writer) /* Generator.t:43 */
    { /* Generator.t:44 */
        this.optionMap = optionMap; /* Generator.t:45 */
        this.parserFile = parserFile; /* Generator.t:46 */
        setOut(writer); /* Generator.t:47 */
    } /* Generator.t:48 */

    private void processOptionPath(Map<Character, Node> nodeMap) /* Generator.t:50 */
    { /* Generator.t:51 */
        out.write("\n        switch (c)\n        {"); /* Generator.t:52~54 */
        for (Map.Entry<Character, Node> entry : nodeMap.entrySet()) /* Generator.t:55 */
        { /* Generator.t:56 */
            char c = entry.getKey(); /* Generator.t:57 */
            Node node = entry.getValue(); /* Generator.t:58 */
            if (node.pathSet == null) /* Generator.t:59 */
            { /* Generator.t:60 */
                out.write("\n            case \'"); /* Generator.t:61~62 */
                out.print(c); /* Generator.t:62 */
                out.write("\': case \'"); /* Generator.t:62 */
                out.print(Utility.toLowerCase(c)); /* Generator.t:62 */
                out.write("\':"); /* Generator.t:62 */
                // The first char has been classified by the switch /* Generator.t:63 */
                processSimplePath(node.path.substring(1), node.name, node.isLeaf()); /* Generator.t:64 */
            } /* Generator.t:65 */
            else /* Generator.t:66 */
            { /* Generator.t:67 */
                for (Map.Entry<Character, PathElement> pathEntry : node.pathSet.elemMap.entrySet()) /* Generator.t:68 */
                { /* Generator.t:69 */
                    char ch = pathEntry.getKey(); /* Generator.t:70 */
                    PathElement element = pathEntry.getValue(); /* Generator.t:71 */

                    String varName = node.name.substring(0, node.name.length() - 1) + ch; /* Generator.t:73 */
                    String methodName = node.name + "s"; /* Generator.t:74 */
                    // The first char has been classified by the switch /* Generator.t:75 */
                    String path = element.path.substring(1); /* Generator.t:76 */

                    out.write("\n            case \'"); /* Generator.t:78~79 */
                    out.print(ch); /* Generator.t:79 */
                    out.write("\': case \'"); /* Generator.t:79 */
                    out.print(Utility.toLowerCase(ch)); /* Generator.t:79 */
                    out.write("\':"); /* Generator.t:79 */

                    String branchPath = null; /* Generator.t:81 */
                    if (element.branchSet.isEmpty()) /* Generator.t:82 */
                    { /* Generator.t:83 */
                        processSimplePath(path, methodName, true); /* Generator.t:84 */
                    } /* Generator.t:85 */
                    else if ((branchPath = element.getSingleBranchPath()) != null) /* Generator.t:86 */
                    { /* Generator.t:87 */
                        // The first char has been classified by the switch /* Generator.t:88 */
                        int length = element.getSingleBranchPrefixLength() - 1; /* Generator.t:89 */
                        out.write("\n                int i"); /* Generator.t:90~91 */
                        out.print(varName); /* Generator.t:91 */
                        out.write(" = Util.prefixMatch(param, ++p, end, \""); /* Generator.t:91 */
                        out.print(path); /* Generator.t:91 */
                        out.write("\", \""); /* Generator.t:91 */
                        out.print(Utility.toLowerCase(path)); /* Generator.t:91 */
                        out.write("\");\n                return classify"); /* Generator.t:91~92 */
                        out.print(methodName); /* Generator.t:92 */
                        out.write("(start, (i"); /* Generator.t:92 */
                        out.print(varName); /* Generator.t:92 */
                        out.write(" == "); /* Generator.t:92 */
                        out.print(length); /* Generator.t:92 */
                        out.write(" ? Util.prefixMatch(param, p + i"); /* Generator.t:92 */
                        out.print(varName); /* Generator.t:92 */
                        out.write(", end, \""); /* Generator.t:92 */
                        out.print(branchPath); /* Generator.t:92 */
                        out.write("\", \""); /* Generator.t:92 */
                        out.print(Utility.toLowerCase(branchPath)); /* Generator.t:92 */
                        out.write("\") : 0) + p + i"); /* Generator.t:92 */
                        out.print(varName); /* Generator.t:92 */
                        out.write(", flag);"); /* Generator.t:92 */
                    } /* Generator.t:93 */
                    else /* Generator.t:94 */
                    { /* Generator.t:95 */
                        out.write("\n                "); /* Generator.t:96~97 */
                        checkPathElement(element, path, "            ", varName, true); /* Generator.t:98 */
                        out.write("\n                return classify"); /* Generator.t:99~100 */
                        out.print(methodName); /* Generator.t:100 */
                        out.write("(start, p, flag);"); /* Generator.t:100 */
                    } /* Generator.t:101 */
                } /* Generator.t:102 */
            } /* Generator.t:103 */
        } /* Generator.t:104 */
        out.write("\n            default:\n                return option.classifyBadOption(param, start, end, flag);\n        }"); /* Generator.t:105~108 */
    } /* Generator.t:109 */

    private void processSimplePath(String path, String name, boolean isLeaf) /* Generator.t:111 */
    { /* Generator.t:112 */
        if (path.length() == 0) /* Generator.t:113 */
        { /* Generator.t:114 */
            out.write("\n                return classify"); /* Generator.t:115~116 */
            out.print(name); /* Generator.t:116 */
            out.write("(start, ++p, flag);"); /* Generator.t:116 */
        } /* Generator.t:117 */
        else if (isLeaf) /* Generator.t:118 */
        { /* Generator.t:119 */
            out.write("\n                return classify"); /* Generator.t:120~121 */
            out.print(name); /* Generator.t:121 */
            out.write("(start, Util.prefixMatch(param, ++p, end, \""); /* Generator.t:121 */
            out.print(path); /* Generator.t:121 */
            out.write("\", \""); /* Generator.t:121 */
            out.print(Utility.toLowerCase(path)); /* Generator.t:121 */
            out.write("\") + p, flag);"); /* Generator.t:121 */
        } /* Generator.t:122 */
        else /* Generator.t:123 */
        { /* Generator.t:124 */
            out.write("\n                int i"); /* Generator.t:125~126 */
            out.print(name); /* Generator.t:126 */
            out.write(" = Util.prefixMatch(param, ++p, end, \""); /* Generator.t:126 */
            out.print(path); /* Generator.t:126 */
            out.write("\", \""); /* Generator.t:126 */
            out.print(Utility.toLowerCase(path)); /* Generator.t:126 */
            out.write("\");\n                return classify"); /* Generator.t:126~127 */
            out.print(name); /* Generator.t:127 */
            out.write("(start, p + i"); /* Generator.t:127 */
            out.print(name); /* Generator.t:127 */
            out.write(", flag, i"); /* Generator.t:127 */
            out.print(name); /* Generator.t:127 */
            out.write(" == "); /* Generator.t:127 */
            out.print(path.length()); /* Generator.t:127 */
            out.write(");"); /* Generator.t:127 */
        } /* Generator.t:128 */
    } /* Generator.t:129 */

    private void processNode(Node node) /* Generator.t:131 */
    { /* Generator.t:132 */
        String methodName = (node.pathSet == null) ? node.name : node.name + "s"; /* Generator.t:133 */
        boolean needCheckClassifyChildren = /* Generator.t:134 */
                node.path != null && node.path.length() > 1 && !node.isLeaf(); /* Generator.t:135 */
        out.write("\n    int classify"); /* Generator.t:136~137 */
        out.print(methodName); /* Generator.t:137 */
        out.write("(int start, int p, boolean flag"); /* Generator.t:137 */
        if (needCheckClassifyChildren) /* Generator.t:138 */
        { /* Generator.t:139 */
            out.write(", boolean classifyChildren"); /* Generator.t:140 */
        } /* Generator.t:141 */
        out.write(")\n    {\n        char c;\n        if (p == end || (c = param[p]) == \'=\' || Option.isDelimiter(c))\n        {\n            "); /* Generator.t:142~147 */
        processClassifiedOptionSet(node); /* Generator.t:148 */
        out.write("\n        }"); /* Generator.t:149~150 */

        if (node.isLeaf()) /* Generator.t:152 */
        { /* Generator.t:153 */
            out.write("\n        return option.classifyBadOption(param, start, end, flag);"); /* Generator.t:154~155 */
        } /* Generator.t:156 */
        else /* Generator.t:157 */
        { /* Generator.t:158 */
            if (needCheckClassifyChildren) /* Generator.t:159 */
            { /* Generator.t:160 */
                out.write("\n        if (!classifyChildren)\n        {\n            return option.classifyBadOption(param, start, end, flag);\n        }"); /* Generator.t:161~165 */
            } /* Generator.t:166 */
            processOptionPath(node.children); /* Generator.t:167 */
        } /* Generator.t:168 */
        out.write("\n    }\n"); /* Generator.t:169~171 */

        if (!node.isLeaf()) /* Generator.t:173 */
        { /* Generator.t:174 */
            for (Node childNode : node.children.values()) /* Generator.t:175 */
            { /* Generator.t:176 */
                processNode(childNode); /* Generator.t:177 */
            } /* Generator.t:178 */
        } /* Generator.t:179 */
    } /* Generator.t:180 */

    private void checkPathSet(PathSet pathSet, String indent, String varName) /* Generator.t:182 */
    { /* Generator.t:183 */
        boolean first = true; /* Generator.t:184 */
        for (Map.Entry<Character, PathElement> entry : pathSet.elemMap.entrySet()) /* Generator.t:185 */
        { /* Generator.t:186 */
            PathElement element = entry.getValue(); /* Generator.t:187 */
            out.write("\n"); /* Generator.t:188~189 */
            out.print(indent); /* Generator.t:189 */
            if (first) /* Generator.t:190 */
            { /* Generator.t:191 */
                first = false; /* Generator.t:192 */
            } /* Generator.t:193 */
            else /* Generator.t:194 */
            { /* Generator.t:195 */
                out.write("else "); /* Generator.t:196 */
            } /* Generator.t:197 */
            checkPathElement(element, element.path, indent, varName, false); /* Generator.t:198 */
        } /* Generator.t:199 */
    } /* Generator.t:200 */

    private void checkPathElement(PathElement element, String path, String indent, String varName, boolean root) /* Generator.t:202 */
    { /* Generator.t:203 */
        if (root) /* Generator.t:204 */
        { /* Generator.t:205 */
            out.write("int "); /* Generator.t:206 */
        } /* Generator.t:207 */
        else /* Generator.t:208 */
        { /* Generator.t:209 */
            out.write("if (("); /* Generator.t:210 */
        } /* Generator.t:211 */
        out.write("i"); /* Generator.t:212 */
        out.print(varName); /* Generator.t:212 */
        out.write(" = Util.prefixMatch(param, p, end, \""); /* Generator.t:212 */
        out.print(path); /* Generator.t:212 */
        out.write("\", \""); /* Generator.t:212 */
        out.print(Utility.toLowerCase(path)); /* Generator.t:212 */
        out.write("\")"); /* Generator.t:212 */
        if (root) /* Generator.t:213 */
        { /* Generator.t:214 */
            out.write(";\n                "); /* Generator.t:215~216 */
        } /* Generator.t:217 */
        else /* Generator.t:218 */
        { /* Generator.t:219 */
            out.write(") > 0)\n"); /* Generator.t:220~221 */
            out.print(indent); /* Generator.t:221 */
            out.write("{\n"); /* Generator.t:221~222 */
            out.print(indent); /* Generator.t:222 */
            out.write("    "); /* Generator.t:222 */
        } /* Generator.t:223 */
        out.write("p += i"); /* Generator.t:224 */
        out.print(varName); /* Generator.t:224 */
        out.write(";"); /* Generator.t:224 */

        boolean first = true; /* Generator.t:226 */
        for (Map.Entry<Integer, PathSet> entry : element.branchSet.entrySet()) /* Generator.t:227 */
        { /* Generator.t:228 */
            // The first char has been classified by the switch /* Generator.t:229 */
            int len = root ? entry.getKey() - 1: entry.getKey(); /* Generator.t:230 */
            out.write("\n"); /* Generator.t:231~232 */
            out.print(indent); /* Generator.t:232 */
            out.write("    "); /* Generator.t:232 */
            if (first) /* Generator.t:233 */
            { /* Generator.t:234 */
                first = false; /* Generator.t:235 */
            } /* Generator.t:236 */
            else /* Generator.t:237 */
            { /* Generator.t:238 */
                out.write("else "); /* Generator.t:239 */
            } /* Generator.t:240 */
            out.write("if (i"); /* Generator.t:241 */
            out.print(varName); /* Generator.t:241 */
            out.write(" == "); /* Generator.t:241 */
            out.print(len); /* Generator.t:241 */
            out.write(")\n"); /* Generator.t:241~242 */
            out.print(indent); /* Generator.t:242 */
            out.write("    {"); /* Generator.t:242 */
            checkPathSet(entry.getValue(), indent + "        ", varName); /* Generator.t:243 */
            out.write("\n"); /* Generator.t:244~245 */
            out.print(indent); /* Generator.t:245 */
            out.write("    }"); /* Generator.t:245 */
        } /* Generator.t:246 */
        if (!root) /* Generator.t:247 */
        { /* Generator.t:248 */
            out.write("\n"); /* Generator.t:249~250 */
            out.print(indent); /* Generator.t:250 */
            out.write("}"); /* Generator.t:250 */
        } /* Generator.t:251 */
    } /* Generator.t:252 */

    private void processClassifiedOptionSet(Node node) /* Generator.t:254 */
    { /* Generator.t:255 */
        if (node.switchOptionCount > 0 || node.valuedOptionCount == 1) /* Generator.t:256 */
        { /* Generator.t:257 */
            out.write("int q = "); /* Generator.t:258 */
        } /* Generator.t:259 */
        out.write("Option.valuedOption(param, p, end);\n            "); /* Generator.t:260~261 */
        if (node.switchOptionCount == 0) /* Generator.t:262 */
        { /* Generator.t:263 */
            if (node.valuedOptionCount == 1) /* Generator.t:264 */
            { /* Generator.t:265 */
                out.write("return flag ? q < 0 ? option.reportMissingValue(param, start, end)\n                                : OptionEnum."); /* Generator.t:266~267 */
                out.print(node.valuedOption); /* Generator.t:267 */
                out.write(".setValue(param, start, end, p, q, option)\n                        : option.classifyBadOption(param, start, end, false);"); /* Generator.t:267~268 */
            } /* Generator.t:269 */
            else /* Generator.t:270 */
            { /* Generator.t:271 */
                out.write("return flag ? option.reportAmbiguousOption(param, start, end, true, \""); /* Generator.t:272 */
                out.print(Control.toString(node.optionSet)); /* Generator.t:272 */
                out.write("\")\n                        : option.classifyBadOption(param, start, end, false);"); /* Generator.t:272~273 */
            } /* Generator.t:274 */
        } /* Generator.t:275 */
        else if (node.switchOptionCount == 1) /* Generator.t:276 */
        { /* Generator.t:277 */
            if (node.valuedOptionCount == 0) /* Generator.t:278 */
            { /* Generator.t:279 */
                out.write("return q < 0 ? OptionEnum."); /* Generator.t:280 */
                out.print(node.switchOption); /* Generator.t:280 */
                out.write(".setBooleanValue(flag, p, option)\n                         : flag ? option.reportValueNotRequired(param, start, end)\n                                : option.classifyBadOption(param, start, end, false);"); /* Generator.t:280~282 */
            } /* Generator.t:283 */
            else if (node.valuedOptionCount == 1) /* Generator.t:284 */
            { /* Generator.t:285 */
                out.write("return q < 0 ? OptionEnum."); /* Generator.t:286 */
                out.print(node.switchOption); /* Generator.t:286 */
                out.write(".setBooleanValue(flag, p, option)\n                         : flag ? OptionEnum."); /* Generator.t:286~287 */
                out.print(node.valuedOption); /* Generator.t:287 */
                out.write(".setValue(param, start, end, p, q, option)\n                                : option.classifyBadOption(param, start, end, false);"); /* Generator.t:287~288 */
            } /* Generator.t:289 */
            else /* Generator.t:290 */
            { /* Generator.t:291 */
                out.write("return flag ? option.reportAmbiguousOption(param, start, end, true, \""); /* Generator.t:292 */
                out.print(Control.toString(node.optionSet)); /* Generator.t:292 */
                out.write("\")\n                        : q < 0 ? OptionEnum."); /* Generator.t:292~293 */
                out.print(node.switchOption); /* Generator.t:293 */
                out.write(".setBooleanValue(false, p, option)\n                                : option.classifyBadOption(param, start, end, false);"); /* Generator.t:293~294 */
            } /* Generator.t:295 */
        } /* Generator.t:296 */
        else /* Generator.t:297 */
        { /* Generator.t:298 */
            if (node.valuedOptionCount == 1) /* Generator.t:299 */
            { /* Generator.t:300 */
                out.write("return q < 0 ? option.reportAmbiguousOption(param, start, end, flag, \""); /* Generator.t:301 */
                out.print(Control.toString(node.optionSet)); /* Generator.t:301 */
                out.write("\")\n                         : flag ? OptionEnum."); /* Generator.t:301~302 */
                out.print(node.valuedOption); /* Generator.t:302 */
                out.write(".setValue(param, start, end, p, q, option)\n                                : option.classifyBadOption(param, start, end, false);"); /* Generator.t:302~303 */
            } /* Generator.t:304 */
            else /* Generator.t:305 */
            { /* Generator.t:306 */
                out.write("return (q < 0 || flag) ? option.reportAmbiguousOption(param, start, end, flag, \""); /* Generator.t:307 */
                out.print(Control.toString(node.optionSet)); /* Generator.t:307 */
                out.write("\")\n                                   : option.classifyBadOption(param, start, end, false);"); /* Generator.t:307~308 */
            } /* Generator.t:309 */
        } /* Generator.t:310 */
    } /* Generator.t:311 */

}
